
项目地址: git@git.oschina.net:czbkiosweibo/iOSWeibo999.git



Swift中的可选:可选不能直接拿来操作
    1.!: 强制拆包.拿到可选里面的真正的值,强制拆包如果没有值会崩溃
        1.如果确定没问题就强制拆包
        2.如果不确定,判断不等于nil才拆包.或者可选绑定
            var aa: Int? = 10
            if let a = aa { // 先判断aa是否有值,如果aa有值,就将aa强制拆包,让后赋值给a
                // 在代码里面直接使用a就可以,不用在拿着aa在强制拆包
            } else {
                // 如果aa没有值.直接进入到这个分支
            }
    2.?:
        1.statuses?.count ?表示statuses才往后面执行,如果没有值就停下来不执行后面的代码,并且整个表达式返回nil
        2.delegate?.visitroViewDidClickLoginButton?(): visitroViewDidClickLoginButton?()表示,兑现实现了这个方法就调用这个方法,如果没实现就不调用这个方法,并且返回nil
    5.??
        1. statuses?.count ?? 0: ?? 前面的可选是否有值,如果有值就使用前面的值,如果前面的可选没有值,为nil 就会使用 ?? 后面的值
    3.as?
        1.let dict = result as? [String: AnyObject]: 将result来类型转换成 [String: AnyObject],as?表示我们认为可能转成功也可能转失败,所以类型转换的结果是一个[String: AnyObject]?,真的转失败了以不会崩溃只会返回nil
    4.as!
        1.let dict = result as! [String: AnyObject]:将result来类型转换成 [String: AnyObject],as!表示我们认为一定能够转成功,所以类型转换的结果是一个[String: AnyObject],不会带?,但是一旦装换失败,程序就崩溃了
    5.nameLabel?.text = status?.user?.screen_name,当使用可选赋值的时候,需要看左边的变量的类型

公司开发一般会分debug 和release 版本
    debug: 开发调试
    release: 上线的
    不仅客户端需要 debug 和 release, 服务器也会有 debug 和 release, 服务器的 debug 和 release 的接口地址会不一样的
    服务器的 debug 和 release 的接口一般只是前面的域名不一样,后面的参数都是一样的
        debug: https://debug.api.weibo.com/oauth2/access_token
        release: https://api.weibo.com/oauth2/access_token

1.OC使用Swift的类,需要导入 "产品名称-Swift.h", 产品名称不要数字开头,也不要包含 -    #import "单例-Swift.h"
2.Swift使用OC的类,需要桥接文件,系统会自动创建这个文件,在桥接文件里面 #import "CZTestView.h",注意如果使用Pod管理的不需要桥接,只有自己写的或拖进来的OC文件才需要桥接

访客视图
    1.访客视图,登陆时一个界面,没有又是另外一个界面
        实现:在loadView里面的设置,抽取基类
    2.每个访客视图的内容不一样
        1.自定义访客视图,
        2.访客是图懒加载所有的控件
        3.添加子控件,添加约束,是在 init(frame: CGRect), 外部调用 UIView() / [[UIView alloc] init], 最终都会走 UIView(frame: CGRect),在添加约束之前,view必须有父控件
        4.在自定义访客视图里面提供setupVisitor,让别人来设置访客视图,单独在每个控制器来设置访客视图,最后在CZBaseTableViewController里来判断不同的控制器设置对应的访客视图内容
        5.使用核心动画让转轮旋转,注意当核心动画看不到,在切回来动画会停止需要加: rotation.removedOnCompletion = false

Oauth授权:
    1.了解授权流程
    2.加载登陆界面,
        1.创建控制器里面有一个webView
        2.使用webView加载这个登陆界面
        3.查看登陆界面的API
            1.API文档主要看的内容
                1.接口说明  ***
                2.请求的URL    *****
                3.请求方式      *****
                4.请求参数      *****
                5.返回数据      *****
    3.拦截webView加载
        1.不是授权回调地址,让他加载
        2.加载的授权回调地址,说明点击的是 取消 或 授权
    4.通过query开头是code=授权,否则是取消
    5.点击授权,发送POST请求获取access_token
        1.截取code
        2.查看API文档主要看的内容
        3.调用AFN.POST
    6.字典转模型
        1.setValuesForKeysWithDictionary
            1./// 字典中的key在模型中找不到对应的属性
            override func setValue(value: AnyObject?, forUndefinedKey key: String) {
                print("forUndefinedKey: \(key)")
            }
        2.属性要定义为可选
            1.基本数据类型不能使用可选,给一个默认值
    7.CZUserAccountViewModel: 模型的所有操作都由它来做
        1.CZUserAccountViewModel是一个单例.
            1.单例的作用:在程序的运行过程中只有唯一一个,访问容易,缺点,直到程序退出才销毁.占用内存.单例不好继承
    7.保存模型
        1.让模型实现NSCoding
        2.保存对象: NSKeyedArchiver.archiveRootObject(userAccount!, toFile: accountPath)
    8.解档模型:
        1. NSKeyedUnarchiver.unarchiveObjectWithFile(accountPath) as? CZUserAccount

界面切换
    1.画图,分析清楚逻辑,和需要的界面
    2.搭建单独的界面
    3.处理判断条件
    4.根据逻辑来做跳转处理

首页界面:
    1.首页布局
    2.数据
        1.如果有数据,就先请求一下数据
        2.如果没有数据,先做界面

微博数据:
    1.请求数据: 查看API
    2.字典转模型,不要面向字典开发
    3.setValuesForKeysWithDictionary
        1./// 字典中的key在模型中找不到对应的属性
        override func setValue(value: AnyObject?, forUndefinedKey key: String) {
            print("forUndefinedKey: \(key)")
        }
    4.微博模型里面有一个user模型,需要拦截系统的setValue:forKey:,系统的setValue:forKey:会将服务器返回的user字典赋值给user属性(实际上是CZUser模型).自己字典转模型,赋值给user属性
自定义cell:
    1.以前返回不同高度的cell是通过: tableView:heightForRowAtIndexPath:, 系统会让contentView和cell一样大
    2.tableView.cell的高度使用通过cell里面的子空间自动约束来确定高度,要约束好cell.contentView,系统会根据contentView的高度来设置cell的高度.一定要约束好contentView的约束
    3.完整原创view(CZStatusOrigianalView)

下拉刷新:
    1.自定义View
    2.自定义View放哪里, 放在tableView里面,往上偏移自身的高度
    3.有3状态
    4.怎么切换这个状态,自己来监听tableView的滚动,不要使用tableView的代理来监听滚动


日期处理:
    1.新浪返回的字符串不好比较时间,将字符串转成系统的NSDate,
    2.使用NSDate来比较更放便
    3.返回对应的字符串